home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / xspawnve.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-11-27  |  16.7 KB  |  592 lines

  1. /*
  2.  *                   XSPAWN
  3.  *                Version 1.33
  4.  *  (C) Copyright 1990 Whitney Software, Inc.
  5.  *             All Rights Reserved
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #ifdef LATTICE
  13. #include <dos.h>
  14. #else
  15. #include <io.h>
  16. #endif
  17. #include "xspawnp.h"
  18.  
  19. typedef struct _vector
  20. {
  21.     char number;                       /* vector number */
  22.     char flag;                         /* 0-CURRENT, 1-IRET, 2-free, 3-end */
  23.     unsigned int vseg;                 /* vector segment */
  24.     unsigned int voff;                 /* vector offset */
  25. }
  26. VECTOR;
  27.  
  28. static void savevect( void );
  29. static int testfile( char *, char *, int * );
  30. static int tempfile( char *, int * );
  31. static int cmdenv( char **, char **, char *, char **, char ** );
  32. static int doxspawn( char *, char **, char ** );
  33. #ifdef LATTICE
  34. extern int __xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
  35. extern int __xsize( unsigned int, long *, long * );
  36. extern int __chkems( char *, int * );
  37. extern int __savemap( char * );
  38. extern int __restmap( char * );
  39. extern int __getems( int, int * );
  40. extern int __dskspace( int, unsigned int *, unsigned int * );
  41. extern int __getrc( void );
  42. extern int __create( char *, int * );
  43. extern int __getcd( int, char * );
  44. extern int __getdrv( void );
  45. extern void __getvect( int, unsigned int *, unsigned int * );
  46. extern void __setvect( VECTOR * );
  47. #else
  48. extern int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
  49. extern int _xsize( unsigned int, long *, long * );
  50. extern int _chkems( char *, int * );
  51. extern int _savemap( char * );
  52. extern int _restmap( char * );
  53. extern int _getems( int, int * );
  54. extern int _dskspace( int, unsigned int *, unsigned int * );
  55. extern int _getrc( void );
  56. extern int _create( char *, int * );
  57. extern int _getcd( int, char * );
  58. extern int _getdrv( void );
  59. extern void _getvect( int, unsigned int *, unsigned int * );
  60. extern void _setvect( VECTOR * );
  61. #endif
  62.  
  63. #ifdef LATTICE
  64. extern char **environ;
  65. #endif
  66.  
  67. int _swap = 0;                         /* if 0, do swap */
  68. char *_swappath = NULL;                /* swap path */
  69. int _useems = 0;                       /* if 0, use EMS */
  70. int _required = 0;                     /* child memory requirement in K */
  71. static long swapsize;                  /* swap size requirement in bytes */
  72. static int ems = 2;                    /* if 0, EMS is available */
  73. static int mapsize;                    /* size of page map information */
  74. static unsigned int tempno = 1;        /* tempfile number */
  75. static char errtab[] =                 /* error table */
  76. {
  77.     0,
  78.     EINVAL,
  79.     ENOENT,
  80.     ENOENT,
  81.     EMFILE,
  82.     EACCES,
  83.     EBADF,
  84.     ENOMEM,
  85.     ENOMEM,
  86.     ENOMEM,
  87.     E2BIG,
  88.     ENOEXEC,
  89.     EINVAL,
  90.     EINVAL,
  91.     -1,
  92.     EXDEV,
  93.     EACCES,
  94.     EXDEV,
  95.     ENOENT,
  96.     -1
  97. };
  98. static VECTOR vectab1[] =
  99. {
  100.     0,    1,     0,  0,
  101.     1,    1,     0,  0,
  102.     2,    1,     0,  0,
  103.     3,    1,     0,  0,
  104.     0x1B, 1,     0,  0,
  105.     0x23, 1,     0,  0,
  106.     0,    2,     0,  0,                /* free record */
  107.     0,    2,     0,  0,                /* free record */
  108.     0,    2,     0,  0,                /* free record */
  109.     0,    2,     0,  0,                /* free record */
  110.     0,    2,     0,  0,                /* free record */
  111.     0,    2,     0,  0,                /* free record */
  112.     0,    2,     0,  0,                /* free record */
  113.     0,    2,     0,  0,                /* free record */
  114.     0,    2,     0,  0,                /* free record */
  115.     0,    2,     0,  0,                /* free record */
  116.     0,    2,     0,  0,                /* free record */
  117.     0,    2,     0,  0,                /* free record */
  118.     0,    2,     0,  0,                /* free record */
  119.     0,    2,     0,  0,                /* free record */
  120.     0,    2,     0,  0,                /* free record */
  121.     0,    2,     0,  0,                /* free record */
  122.     0,    2,     0,  0,                /* free record */
  123.     0,    2,     0,  0,                /* free record */
  124.     0,    2,     0,  0,                /* free record */
  125.     0,    2,     0,  0,                /* free record */
  126.     0,    2,     0,  0,                /* free record */
  127.     0,    2,     0,  0,                /* free record */
  128.     0,    2,     0,  0,                /* free record */
  129.     0,    2,     0,  0,                /* free record */
  130.     0,    3,     0,  0                 /* end record */
  131. };
  132. static VECTOR vectab2[ sizeof vectab1 / sizeof vectab1[ 0 ]];
  133.  
  134. int addvect( number, opcode )
  135. int number;
  136. int opcode;
  137. {
  138.     register VECTOR *vect = vectab1;
  139.  
  140.     if ( number < 0 || number > 0xFF ||
  141.         ( opcode != IRET && opcode != CURRENT ))
  142.     {
  143.         errno = EINVAL;
  144.         return( -1 );
  145.     }
  146.  
  147.     /* see if number is already in table */
  148.     while ( vect->flag != 3 && ( vect->flag == 2 ||
  149.         vect->number != ( char )number ))
  150.     {
  151.         vect++;
  152.     }
  153.  
  154.     if ( vect->flag == 3 )
  155.     {
  156.         /* look for a free record */
  157.         vect = vectab1;
  158.         while ( vect->flag == CURRENT || vect->flag == IRET )
  159.             vect++;
  160.     }
  161.  
  162.     if ( vect->flag != 3 )
  163.     {
  164.         vect->number = ( char )number;
  165.         vect->flag = ( char )opcode;
  166.         if ( opcode == CURRENT )
  167. #ifdef LATTICE
  168.             __getvect( number, &vect->vseg, &vect->voff );
  169. #else
  170.             _getvect( number, &vect->vseg, &vect->voff );
  171. #endif
  172.         return( 0 );
  173.     }
  174.  
  175.     errno = ENOMEM;
  176.     return( -1 );
  177. }
  178.  
  179. static void savevect()
  180. {
  181.     register VECTOR *vect1 = vectab1;
  182.     register VECTOR *vect2 = vectab2;
  183.  
  184.     while ( vect1->flag != 3 )
  185.     {
  186.         if ( vect1->flag != 2 )
  187.         {
  188.             vect2->number = vect1->number;
  189.             vect2->flag = CURRENT;
  190. #ifdef LATTICE
  191.             __getvect( vect1->number, &vect2->vseg, &vect2->voff );
  192. #else
  193.             _getvect( vect1->number, &vect2->vseg, &vect2->voff );
  194. #endif
  195.         }
  196.         else
  197.             vect2->flag = 2;           /* free */
  198.         vect1++;
  199.         vect2++;
  200.     }
  201.     vect2->flag = 3;                   /* end */
  202. }
  203.  
  204. static int testfile( p, file, handle )
  205. register char *p;
  206. register char *file;
  207. int *handle;
  208. {
  209.     unsigned int startno = tempno;
  210.     int drive = ( *file | 32 ) - 96;   /* a = 1, b = 2, etc. */
  211.     int root;
  212.     unsigned int bytes;                /* bytes per cluster */
  213.     unsigned int clusters;             /* free clusters */
  214.     int need;                          /* clusters needed for swap file */
  215.     int rc;                            /* return code */
  216.  
  217.     if ( file + 2 == p )
  218.     {
  219.         *p++ = '\\';
  220. #ifdef LATTICE
  221.         if ( __getcd( drive, p ))      /* get current directory */
  222. #else
  223.         if ( _getcd( drive, p ))       /* get current directory */
  224. #endif
  225.             return( 1 );               /* invalid drive */
  226.         p = file + strlen( file );
  227.     }
  228.     else
  229.     {
  230.         *p = '\0';
  231.         if ( access( file, 0 ))
  232.             return( 1 );               /* path does not exist */
  233.     }
  234.     if ( *( p - 1 ) != '\\' && *( p - 1 ) != '/' )
  235.         *p++ = '\\';
  236.     if ( p - file == 3 )
  237.         root = 1;                      /* is root directory */
  238.     else
  239.         root = 0;                      /* is not root directory */
  240.     strcpy( p, "swp" );
  241.     p += 3;
  242.  
  243. #ifdef LATTICE
  244.     if ( __dskspace( drive, &bytes, &clusters ) != 0 )
  245. #else
  246.     if ( _dskspace( drive, &bytes, &clusters ) != 0 )
  247. #endif
  248.         return( 1 );                   /* invalid drive */
  249.     need = ( int )( swapsize / bytes );
  250.     if ( swapsize % bytes )
  251.         need++;
  252.     if ( root == 0 )                   /* if subdirectory */
  253.         need++;                        /* in case the directory needs space */
  254.     if ( clusters < ( unsigned int )need )
  255.         return( 1 );                   /* insufficient free disk space */
  256.  
  257.     do
  258.     {
  259. again:  tempno = ( ++tempno ) ? tempno : 1;
  260.         if ( tempno == startno )
  261.             return( 1 );               /* extremely unlikely */
  262. #ifdef LATTICE
  263.         stcu_d( p, tempno );
  264. #else
  265.         ltoa(( long )tempno, p, 10 );
  266. #endif
  267.     }
  268.     while ( !access( file, 0 ));
  269.  
  270. /*
  271.  *  The return code from _create will equal 80 if the user is running DOS 3.0
  272.  *  or above and the file was created by another program between the access
  273.  *  call and the _create call.
  274.  */
  275.  
  276. #ifdef LATTICE
  277.     if (( rc = __create( file, handle )) == 80 )
  278. #else
  279.     if (( rc = _create( file, handle )) == 80 )
  280. #endif
  281.         goto again;
  282.     return( rc );
  283. }
  284.  
  285. static int tempfile( file, handle )
  286. char *file;
  287. int *handle;
  288. {
  289.     register char *s = _swappath;
  290.     register char *p = file;
  291.  
  292.     if ( s )
  293.     {
  294.         for ( ;; s++ )
  295.         {
  296.             while ( *s && *s != ';' )
  297.                 *p++ = *s++;
  298.             if ( p > file )
  299.             {
  300.                 if ( p == file + 1 || file[ 1 ] != ':' )
  301.                 {
  302. #ifdef MSC4
  303.                     memcpy( file + 2, file, ( int )( p - file ));
  304. #else
  305.                     memmove( file + 2, file, ( int )( p - file ));
  306. #endif
  307. #ifdef LATTICE
  308.                     *file = ( char )( __getdrv() + 'a' );
  309. #else
  310.                     *file = ( char )( _getdrv() + 'a' );
  311. #endif
  312.                     file[ 1 ] = ':';
  313.                     p += 2;
  314.                 }
  315.                 if ( testfile( p, file, handle ) == 0 )
  316.                     return( 0 );
  317.                 p = file;
  318.             }
  319.             if ( *s == '\0' )
  320.                 break;
  321.         }
  322.     }
  323.     else                               /* try the current directory */
  324.     {
  325. #ifdef LATTICE
  326.         *p++ = ( char )( __getdrv() + 'a' );
  327. #else
  328.         *p++ = ( char )( _getdrv() + 'a' );
  329. #endif
  330.         *p++ = ':';
  331.         if ( testfile( p, file, handle ) == 0 )
  332.             return( 0 );
  333.     }
  334.  
  335.     errno = EACCES;
  336.     return( 1 );
  337. }
  338.  
  339. static int cmdenv( argv, envp, command, env, memory )
  340. char **argv;
  341. char **envp;
  342. char *command;
  343. char **env;
  344. char **memory;
  345. {
  346.     register char **vp;
  347.     unsigned int elen = 0;             /* environment length */
  348.     char *p;
  349.     int cnt;
  350.     int len;
  351.  
  352.     /* construct environment */
  353.  
  354.     if ( envp == NULL )
  355.         envp = environ;
  356.  
  357.     if ( envp )
  358.     {
  359.         for ( vp = envp; *vp; vp++ )
  360.         {
  361.             elen += strlen( *vp ) + 1;
  362.             if ( elen > 32766 )        /* 32K - 2 */
  363.             {
  364.                 errno = E2BIG;
  365.                 return( -1 );
  366.             }
  367.         }
  368.     }
  369.  
  370.     if (( p = malloc( ++elen + 15 )) == NULL )
  371.     {
  372.         errno = ENOMEM;
  373.         return( -1 );
  374.     }
  375.     *memory = p;
  376.  
  377.     *( unsigned int * )&p = *( unsigned int * )&p + 15 & ~15;
  378.     *env = p;
  379.  
  380.     if ( envp )
  381.     {
  382.         for ( vp = envp; *vp; vp++ )
  383.             p = strchr( strcpy( p, *vp ), '\0' ) + 1;
  384.     }
  385.  
  386.     *p = '\0';                         /* final element */
  387.  
  388.     /* construct command-line */
  389.  
  390.     vp = argv;
  391.     p = command + 1;
  392.     cnt = 0;
  393.  
  394.     if ( *vp )
  395.     {
  396.         while ( *++vp )
  397.         {
  398.             *p++ = ' ';
  399.             cnt++;
  400.             len = strlen( *vp );
  401.             if ( cnt + len > 125 )
  402.             {
  403.                 errno = E2BIG;
  404.                 free( *memory );
  405.                 return( -1 );
  406.             }
  407.             strcpy( p, *vp );
  408.             p += len;
  409.             cnt += len;
  410.         }
  411.     }
  412.  
  413.     *p = '\r';
  414.     *command = ( char )cnt;
  415.  
  416.     return(( int )elen );              /* return environment length */
  417. }
  418.  
  419. static int doxspawn( path, argv, envp )
  420. char *path;                      /* file to be executed */
  421. char *argv[];                    /* array of pointers to arguments */
  422. char *envp[];                    /* array of pointers to environment strings */
  423. {
  424.     register int rc = 0;               /* assume do xspawn */
  425.     int doswap = 0;                    /* assume do swap */
  426.     int elen;                          /* environment length */
  427.     char *memory;
  428.     char *env;                         /* environment */
  429.     char command[ 128 ];               /* command-line */
  430.     long totalsize;                    /* parent and free memory in bytes */
  431.     int handle;
  432.     int pages;
  433.     char file[ 79 ];
  434.     char *mapbuf = NULL;               /* buffer for map information */
  435.  
  436.     /* construct the command-line and the environment */
  437.     if (( elen = cmdenv( argv, envp, command, &env, &memory )) == -1 )
  438.         return( -1 );
  439.  
  440.     if ( _swap == 0 )
  441.     {
  442.         if ( _useems == 0 )
  443.         {
  444.             if ( ems == 2 )
  445. #ifdef LATTICE
  446.                 ems = __chkems( "EMMXXXX0", &mapsize );
  447. #else
  448.                 ems = _chkems( "EMMXXXX0", &mapsize );
  449. #endif
  450.             if ( ems == 0 && ( mapbuf = malloc( mapsize )) == NULL )
  451.             {
  452.                 errno = ENOMEM;
  453.                 free( memory );
  454.                 return( -1 );
  455.             }
  456.         }
  457. #ifdef LATTICE
  458.         if (( rc = __xsize(( unsigned int )(( unsigned long )_PSP >> 16 ),
  459.             &swapsize, &totalsize )) == 0 )
  460. #else
  461.         if (( rc = _xsize( _psp, &swapsize, &totalsize )) == 0 )
  462. #endif
  463.         {
  464.             if ( _required == 0 ||
  465.                 totalsize - swapsize - 272 < (( long )_required << 10 ))
  466.             {
  467.                 if ( ems == 0 && _useems == 0 )
  468.                 {
  469.                     pages = ( int )( swapsize >> 14 );
  470.                     if ((( long )pages << 14 ) < swapsize )
  471.                         pages++;
  472. #ifdef LATTICE
  473.                     if ( __savemap( mapbuf ) == 0 &&
  474.                         __getems( pages, &handle ) == 0 )
  475. #else
  476.                     if ( _savemap( mapbuf ) == 0 &&
  477.                         _getems( pages, &handle ) == 0 )
  478. #endif
  479.                         *file = '\0';  /* use EMS */
  480.                     else if ( tempfile( file, &handle ) != 0 )
  481.                         rc = -1;       /* don't do xspawn */
  482.                 }
  483.                 else if ( tempfile( file, &handle ) != 0 )
  484.                     rc = -1;           /* don't do xspawn */
  485.             }
  486.             else
  487.                 doswap = 1;            /* don't do swap */
  488.         }
  489.         else
  490.         {
  491.             errno = errtab[ rc ];
  492.             rc = -1;                   /* don't do xspawn */
  493.         }
  494.     }
  495.     else
  496.         doswap = 1;                    /* don't do swap */
  497.  
  498.     if ( rc == 0 )
  499.     {
  500.         savevect();                    /* save current vectors */
  501. #ifdef LATTICE
  502.         rc = __xspawn( path, command, env, vectab1, doswap, elen, file,
  503.             handle );
  504. #else
  505.         rc = _xspawn( path, command, env, vectab1, doswap, elen, file,
  506.             handle );
  507. #endif
  508. #ifdef LATTICE
  509.         __setvect( vectab2 );          /* restore saved vectors */
  510. #else
  511.         _setvect( vectab2 );           /* restore saved vectors */
  512. #endif
  513.         if ( rc == 0 )
  514. #ifdef LATTICE
  515.             rc = __getrc();            /* get child return code */
  516. #else
  517.             rc = _getrc();             /* get child return code */
  518. #endif
  519.         else
  520.         {
  521.             errno = errtab[ rc ];
  522.             rc = -1;
  523.         }
  524.         /*
  525.          *  If EMS was used, restore the page-mapping state of the expanded
  526.          *  memory hardware.
  527.          */
  528. #ifdef LATTICE
  529.         if ( doswap == 0 && *file == '\0' && __restmap( mapbuf ) != 0 )
  530. #else
  531.         if ( doswap == 0 && *file == '\0' && _restmap( mapbuf ) != 0 )
  532. #endif
  533.         {
  534.             errno = EACCES;
  535.             rc = -1;
  536.         }
  537.     }
  538.  
  539.     if ( mapbuf )
  540.         free( mapbuf );
  541.     free( memory );
  542.     return( rc );
  543. }
  544.  
  545. int xspawnve( modeflag, path, argv, envp )
  546. int modeflag;                    /* execution mode for parent process */
  547. register char *path;             /* file to be executed */
  548. char *argv[];                    /* array of pointers to arguments */
  549. char *envp[];                    /* array of pointers to environment strings */
  550. {
  551.     register char *p;
  552.     char *s;
  553.     int rc = -1;
  554.     char buf[ 80 ];
  555.  
  556.     if ( modeflag != P_WAIT )
  557.     {
  558.         errno = EINVAL;
  559.         return( -1 );
  560.     }
  561.  
  562.     p = strrchr( path, '\\' );
  563.     s = strrchr( path, '/' );
  564.     if ( p == NULL && s == NULL )
  565.         p = path;
  566.     else if ( p == NULL || s > p )
  567.         p = s;
  568.  
  569.     if ( strchr( p, '.' ))
  570.     {
  571.         if ( !access( path, 0 ))
  572.             rc = doxspawn( path, argv, envp );
  573.         /* If file not found, access will have set errno to ENOENT. */
  574.     }
  575.     else
  576.     {
  577.         strcpy( buf, path );
  578.         strcat( buf, ".com" );
  579.         if ( !access( buf, 0 ))
  580.             rc = doxspawn( buf, argv, envp );
  581.         else
  582.         {
  583.             strcpy( strrchr( buf, '.' ), ".exe" );
  584.             if ( !access( buf, 0 ))
  585.                 rc = doxspawn( buf, argv, envp );
  586.             /* If file not found, access will have set errno to ENOENT. */
  587.         }
  588.     }
  589.  
  590.     return( rc );
  591. }
  592.